const vscode = require('vscode');
const fs = require('fs');
const { Application, Servers } = require('./ServerProcess');

/** @type {vscode.ExtensionContext} */
let extensionContext = null;

const servers = new Servers()
/**
 * @implements {vscode.FileDecorationProvider}
 */
class ServerDecorationProvider {
    /**
     * 
     * @param {vscode.Uri} uri 
     * @param {vscode.CancellationToken} token 
     * @returns 
     */
    provideFileDecoration(uri, token) {
        if (uri.scheme !== 'server') {
            return
        }
        const uu = new URLSearchParams(uri.query)
        const filename = uri.path.replace(/^\/+/, "")
        const decoration = new vscode.FileDecoration();
        const status = uu.get("status")
        if (status == Application.STATUS_LAUNCHED) {
            decoration.color = new vscode.ThemeColor('superstatus.success')
            decoration.tooltip = '已启动'
            decoration.badge = '◉'
            return decoration
        }
        if (status == Application.STATUS_STARTING || status == Application.STATUS_STOPING) {
            decoration.color = new vscode.ThemeColor('superstatus.warning')
            decoration.tooltip = '正在执行...'
            decoration.badge = '↻'
        }
        if (!fs.existsSync(filename)) {
            decoration.color = new vscode.ThemeColor('superstatus.invalid')
            decoration.tooltip = '文件不存在'
            return decoration
        }
        if (uu.get('checked') == 0) {
            decoration.color = new vscode.ThemeColor('superstatus.invalid')
            decoration.tooltip = '不启动服务'
            return decoration
        }
        return decoration;
    }

}


class ServerTreeItem extends vscode.TreeItem {
    /**
     * @param {import('./ServerProcess').ServerType & import('./ServerProcess').ServerChildrenType} server 
     */
    constructor(server, checkboxState) {
        super(server.file.title || server.file.name, vscode.TreeItemCollapsibleState.None);
        this.server = server;
        this.description = server.file.name
        if (server.item) {
            this.label = server.item.label
            this.description = server.item.description
        }
        if (server.children) {
            this.collapsibleState = vscode.TreeItemCollapsibleState.Expanded;
        }
        this.hash = server.hash;
        this.checkboxState = checkboxState;
        let status = undefined
        if (this.server.app) {
            this.server.app.disabled = !checkboxState
            status = this.server.app.status

            this.contextValue = `server-status-${status}`
        }
        const query = new URLSearchParams({ checked: this.checkboxState, status });
        this.resourceUri = new vscode.Uri("server", this.server.file.name, "/" + this.server.file.filename, query.toString(), this.hash)
        this.iconPath = this.getIconPath();

    }

    getIconPath() {
        return new vscode.ThemeIcon('server-process');
    }
}

/**
 * @implements {vscode.TreeDataProvider<ServerTreeItem>}
 */

class ServersTreeViewProvider {
    _onDidChangeTreeData = new vscode.EventEmitter();
    onDidChangeTreeData = this._onDidChangeTreeData.event;
    /**
     * @param {ServerFile[]} serverFiles 
     */
    constructor(serverFiles) {
        this.serverFiles = serverFiles;
    }

    /**
     * 
     * @param {import('./ServerProcess').ServerType} element 
     * @returns 
     */
    getChildren(element) {
        if (element) {
            return element.server.children.map(file => new ServerTreeItem(file, this.getCheckboxState(`server-${file.hash}`)))
        }
        return servers.files.map(file => new ServerTreeItem(file, this.getCheckboxState(`server-${file.hash}`)))
    }

    getCheckboxState(name) {
        const status = extensionContext.globalState.get(name)
        if (status === undefined) {
            return vscode.TreeItemCheckboxState.Checked
        }
        return !!status ? vscode.TreeItemCheckboxState.Checked : vscode.TreeItemCheckboxState.Unchecked
    }

    /**
     * 
     * @param {ServerTreeItem} treeItem 
     * @returns 
     */
    getTreeItem(treeItem) {
        setTimeout(() => {
            const name = `server-${treeItem.hash}`
            const checkboxState = this.getCheckboxState(name)
            if (checkboxState !== treeItem.checkboxState) {
                extensionContext.globalState.update(name, treeItem.checkboxState)
                this.refresh()
            }
        }, 0);
        return treeItem;
    }


    refresh() {
        this._onDidChangeTreeData.fire();
    }

    /**
     * @param { vscode.ExtensionContext } context
     * @param {ServerFile[]} serverFiles 
     */
    static initTreeViewItem(context, serverFiles) {
        extensionContext = context
        const serversViewProvider = new ServersTreeViewProvider(serverFiles);
        servers.on("changeStatus", () => {
            serversViewProvider.refresh()
        })
        context.subscriptions.push(
            vscode.window.registerFileDecorationProvider(new ServerDecorationProvider()),
            vscode.window.registerTreeDataProvider("mir_script_activity_servers", serversViewProvider),
            vscode.commands.registerCommand("extension-mir-script.launchAllServer", () => {
                servers.launch()
            }),
            vscode.commands.registerCommand("extension-mir-script.exitAllServer", () => {
                servers.exit()
            }),
            vscode.commands.registerCommand("extension-mir-script.launchServer", (treeItem) => {
                treeItem.server?.app?.launch()
            }),
            vscode.commands.registerCommand("extension-mir-script.exitServer", (treeItem) => {
                treeItem.server?.app?.exit()
            }),
            vscode.commands.registerCommand("extension-mir-script.rebootServer", (treeItem) => {
                treeItem.server?.app?.reboot()
            }),
        )
        return servers
    }
}


module.exports = { ServersTreeViewProvider };